﻿using System.Diagnostics;
using System.Text;

namespace CMWVS.Core.Mono
{
    public class MonoCompiler : RelayCommand<MonoCompilerParams, MonoCompilerResult>
    {
        #region Constructor

        private MonoCompiler()
        {
        }

        public MonoCompiler(Resolver resolver)
        {
            Trace.Assert(null != resolver);
            m_Resolver = resolver;
            this.SetCommands();
        }

        #endregion Constructor

        private Resolver m_Resolver;

        private void SetCommands()
        {
            base.m_CanExecute = () =>
            {
                MonoConfig config = m_Resolver.Get<MonoConfig>();
                return config.IsInstalled;
            };
            base.m_Commmand = (compileParameter) =>
            {
                MonoConfig config = m_Resolver.Get<MonoConfig>();

                // http://www.mono-project.com/Microsoft.Build
                /*
                    To get the project file generated from a solution file (.sln), set the environment variable XBUILD_EMIT_SOLUTION.
                    The Exec task, writes the commands to a temporary file, and executes that with "cmd.exe /q /c" on Windows and "sh" on other platforms. This applies to the Pre and PostBuildEvents in the project files.
                    Usually, dependencies for references are also resolved, like assemblies referenced by a reference itself. But incase an assembly gets resolved via pkg-config, then its dependencies are not resolved.

                    http://permalink.gmane.org/gmane.comp.gnome.mono.bugs/20362
                    https://bugzilla.xamarin.com/show_bug.cgi?id=6969
                    https://bugzilla.xamarin.com/show_bug.cgi?id=19704

                 */
                if ((config.MonoCompiler.Exists) && (null != compileParameter.SLN) && (compileParameter.SLN.SolutionFile.Exists))
                {
                    StringBuilder compilerArguments = new StringBuilder(compileParameter.SLN.SolutionFile.Name);
                    compilerArguments.Append(" ");
                    compilerArguments.Append(compileParameter.Target.Target);

                    if (null != compileParameter.BuildConfiguration)
                    {
                        compilerArguments.Append(" ");
                        compilerArguments.Append(compileParameter.BuildConfiguration.ToString());
                    }

                    if (null != compileParameter.Platform)
                    {
                        compilerArguments.Append(" ");
                        compilerArguments.Append(compileParameter.Platform.ToString());
                    }

                    ProcessStartInfo psi = new ProcessStartInfo(config.MonoCompiler.FullName, compilerArguments.ToString());
                    psi.UseShellExecute = false;
                    psi.WorkingDirectory = compileParameter.SLN.SolutionFile.Directory.FullName;
                    psi.CreateNoWindow = true;
                    psi.RedirectStandardOutput = true;

                    Process p = new Process();
                    p.StartInfo = psi;
                    p.Start();
                    while (!p.StandardOutput.EndOfStream)
                    {
                        compileParameter.Listener.WriteLine(p.StandardOutput.ReadLine());
                    }
                    //p.WaitForExit();
                }

                return new MonoCompilerResult();
            };
        }
    }
}